﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace FGK
{
    class Ortographic : Kamera
    {
        private Wektor w;
        private Wektor u;
        private Wektor v;
        private Wektor a;
        private Wektor b;
        private Wektor c;

        public Ortographic() : base()
        {
        }

        public Ortographic(Wektor p, Wektor t, Stack<Obiekt> s, Stack<Swiatlo> sw, Obrazek o) : base(p, t, s, o, sw)
        {
            Target.normalize();
            w = (-Target) / Target.length();
            u = -(Up.cross(w) / Up.cross(w).length());
            v = w.cross(u);
            a = -2 * u;
            b = -2 * v;
            c = (-1) * u + ((-1) * v) - 0 * w;
        }

        public bool badanieKontrastu(float p1, float p2, float p3, float p4, String kolor)
        {
            float p_max = p1;
            float p_min = p1;
            if (p2 > p_max) p_max = p2;
            if (p2 < p_min) p_min = p2;
            if (p3 > p_max) p_max = p3;
            if (p3 < p_min) p_min = p3;
            if (p4 > p_max) p_max = p4;
            if (p4 < p_min) p_min = p4;

            float C = (p_max - p_min) / (p_max + p_min);

            if (kolor == "R")
            {
                if (C > 0.4f) return true;
            }
            if (kolor == "G")
            {
                if (C > 0.3f) return true;
            }
            if (kolor == "B")
            {
                if (C > 0.6f) return true;
            }
            return false;
        }

        public override void render_scene()
        {
            Console.WriteLine("ortographic");
            Kolor col = new Kolor(0.0f, 1.0f, 0.0f);
           
            //ustalanie rozmiarów pixela
            float szerokoscPixela = 2.0f / Obraz.Szerokosc;
            float wysokoscPixela = 2.0f / Obraz.Wysokosc;

            //algorytm
            for (int i = 0; i < Obraz.Szerokosc; i++)
            {
                for (int j = 0; j < Obraz.Wysokosc; j++)
                {
                    //okreslam srodek
                    float alpha = -1.0f + i*szerokoscPixela;
                    float beta = 1.0f - j*wysokoscPixela;
                    Wektor s1 = c + alpha * a + beta * b;
                    Wektor s2 = c + (alpha + szerokoscPixela) * a + (beta) * b;
                    Wektor s3 = c + (alpha + szerokoscPixela) * a + (beta-wysokoscPixela) * b;
                    Wektor s4 = c + alpha * a + (beta - wysokoscPixela) * b;
                    //definiuję promień
                    Promien ray = new Promien(s2+Position, new Wektor( Target.X, Target.Y, Target.Z));
                    Promien ray2 = new Promien(s2 + Position, new Wektor(Target.X, Target.Y, Target.Z));
                    Promien ray3 = new Promien(s3 + Position, new Wektor(Target.X, Target.Y, Target.Z));
                    Promien ray4 = new Promien(s4 + Position, new Wektor(Target.X, Target.Y, Target.Z));

                    //przecięcia z bryłami
                    for (int k = 0; k < Obiekty.Count; k++)
                    {
                        Obiekty.ElementAt(k).IlePrzeciec(ray);
                        Obiekty.ElementAt(k).IlePrzeciec(ray2);
                        Obiekty.ElementAt(k).IlePrzeciec(ray3);
                        Obiekty.ElementAt(k).IlePrzeciec(ray4);
                    }
                    float finalkolorR=0;
                    float finalkolorG=0;
                    float finalkolorB=0;


                    if (ray.Obiekt != null)
                    {
                        for (int s = 0; s < Swiatlo.Count; s++)
                        {

                            Wektor kier1 = Swiatlo.ElementAt(s).Pozycja - ray.Koniec;
                            kier1.normalize();
                            Promien racl1 = new Promien(ray.Koniec + kier1 * 0.0001f, kier1);
                            for (int k = 0; k < Obiekty.Count; k++)
                            {
                                Obiekty.ElementAt(k).IlePrzeciec(racl1);
                            }
                            //jeśli nic nie zakrywa obiektu
                            if ((racl1.Obiekt == null))
                            {
                                Wektor n = ray.Obiekt.normalna(ray.Koniec);
                                Wektor L = racl1.Kierunek;
                                Wektor R = 2.0f * (n * (L.dot(n))) - L;

                                Kolor tex = ray.Obiekt.texDiff(ray.Koniec);

                                Kolor ambient = Swiatlo.ElementAt(s).Kolor * ray.Obiekt.material.Kolor;
                                Kolor diff = Swiatlo.ElementAt(s).Kolor * (tex.mul(L.dot(n)));
                                Kolor spec = Swiatlo.ElementAt(s).Kolor * ray.Obiekt.material.Specular.mul((float)Math.Pow(R.dot(ray.Kierunek), ray.Obiekt.material.SpecularKoef));
                                Kolor fKolor = ambient + diff + spec;
                                finalkolorR += fKolor.R;
                                finalkolorG += fKolor.G;
                                finalkolorB += fKolor.B;
                            }
                        }
                    }
                    else
                    {
                        if (ray.Obiekt != null)
                        {
                            finalkolorR += ray.Obiekt.material.Kolor.R;
                            finalkolorG += ray.Obiekt.material.Kolor.G;
                            finalkolorB += ray.Obiekt.material.Kolor.B;
                        }
                    }


                    if (ray2.Obiekt != null)
                    {
                        for (int s = 0; s < Swiatlo.Count; s++)
                        {

                            Wektor kier2 = Swiatlo.ElementAt(s).Pozycja - ray2.Koniec;
                            kier2.normalize();
                            Promien racl2 = new Promien(ray2.Koniec + kier2 * 0.0001f, kier2);
                            for (int k = 0; k < Obiekty.Count; k++)
                            {
                                Obiekty.ElementAt(k).IlePrzeciec(racl2);
                            }
                            //jeśli nic nie zakrywa obiektu
                            if ((racl2.Obiekt == null))
                            {
                                Wektor n = ray2.Obiekt.normalna(ray2.Koniec);
                                Wektor L = racl2.Kierunek;
                                Wektor R = 2.0f * (n * (L.dot(n))) - L;

                                Kolor tex = ray2.Obiekt.texDiff(ray2.Koniec);

                                Kolor ambient = Swiatlo.ElementAt(s).Kolor * ray2.Obiekt.material.Kolor;
                                Kolor diff = Swiatlo.ElementAt(s).Kolor * (tex.mul(L.dot(n)));
                                Kolor spec = Swiatlo.ElementAt(s).Kolor * ray2.Obiekt.material.Specular.mul((float)Math.Pow(R.dot(ray2.Kierunek), ray2.Obiekt.material.SpecularKoef));
                                Kolor fKolor = ambient + diff + spec;
                                finalkolorR += fKolor.R;
                                finalkolorG += fKolor.G;
                                finalkolorB += fKolor.B;
                            }
                        }
                    }
                    else
                    {
                        if (ray2.Obiekt != null)
                        {
                            finalkolorR += ray2.Obiekt.material.Kolor.R;
                            finalkolorG += ray2.Obiekt.material.Kolor.G;
                            finalkolorB += ray2.Obiekt.material.Kolor.B;
                        }
                    }

                    if (ray3.Obiekt != null)
                    {
                        for (int s = 0; s < Swiatlo.Count; s++)
                        {

                            Wektor kier3 = Swiatlo.ElementAt(s).Pozycja - ray3.Koniec;
                            kier3.normalize();
                            Promien racl3 = new Promien(ray3.Koniec + kier3 * 0.0001f, kier3);
                            for (int k = 0; k < Obiekty.Count; k++)
                            {
                                Obiekty.ElementAt(k).IlePrzeciec(racl3);
                            }
                            //jeśli nic nie zakrywa obiektu
                            if ((racl3.Obiekt == null))
                            {
                                Wektor n = ray3.Obiekt.normalna(ray3.Koniec);
                                Wektor L = racl3.Kierunek;
                                Wektor R = 2.0f * (n * (L.dot(n))) - L;

                                Kolor tex = ray3.Obiekt.texDiff(ray3.Koniec);

                                Kolor ambient = Swiatlo.ElementAt(s).Kolor * ray3.Obiekt.material.Kolor;
                                Kolor diff = Swiatlo.ElementAt(s).Kolor * (tex.mul(L.dot(n)));
                                Kolor spec = Swiatlo.ElementAt(s).Kolor * ray3.Obiekt.material.Specular.mul((float)Math.Pow(R.dot(ray3.Kierunek), ray3.Obiekt.material.SpecularKoef));
                                Kolor fKolor = ambient + diff + spec;
                                finalkolorR += fKolor.R;
                                finalkolorG += fKolor.G;
                                finalkolorB += fKolor.B;
                            }
                        }
                    }
                    else
                    {
                        if (ray3.Obiekt != null)
                        {
                            finalkolorR += ray3.Obiekt.material.Kolor.R;
                            finalkolorG += ray3.Obiekt.material.Kolor.G;
                            finalkolorB += ray3.Obiekt.material.Kolor.B;
                        }
                    }


                    if (ray4.Obiekt != null)
                    {
                        for (int s = 0; s < Swiatlo.Count; s++)
                        {

                            Wektor kier4 = Swiatlo.ElementAt(s).Pozycja - ray4.Koniec;
                            kier4.normalize();
                            Promien racl4 = new Promien(ray4.Koniec + kier4 * 0.0001f, kier4);
                            for (int k = 0; k < Obiekty.Count; k++)
                            {
                                Obiekty.ElementAt(k).IlePrzeciec(racl4);
                            }
                            //jeśli nic nie zakrywa obiektu
                            if ((racl4.Obiekt == null))
                            {
                                Wektor n = ray4.Obiekt.normalna(ray4.Koniec);
                                Wektor L = racl4.Kierunek;
                                Wektor R = 2.0f * (n * (L.dot(n))) - L;

                                Kolor tex = ray4.Obiekt.texDiff(ray4.Koniec);

                                Kolor ambient = Swiatlo.ElementAt(s).Kolor * ray4.Obiekt.material.Kolor;
                                Kolor diff = Swiatlo.ElementAt(s).Kolor * (tex.mul(L.dot(n)));
                                Kolor spec = Swiatlo.ElementAt(s).Kolor * ray4.Obiekt.material.Specular.mul((float)Math.Pow(R.dot(ray4.Kierunek), ray4.Obiekt.material.SpecularKoef));
                                Kolor fKolor = ambient + diff + spec;
                                finalkolorR += fKolor.R;
                                finalkolorG += fKolor.G;
                                finalkolorB += fKolor.B;
                            }
                        }
                    }
                    else
                    {
                        if (ray4.Obiekt != null)
                        {
                            finalkolorR += ray4.Obiekt.material.Kolor.R;
                            finalkolorG += ray4.Obiekt.material.Kolor.G;
                            finalkolorB += ray4.Obiekt.material.Kolor.B;
                        }
                    }


                    Obraz.setPixel(i, j, new Kolor(finalkolorR / 4 * Swiatlo.Count, finalkolorG / 4 * Swiatlo.Count, finalkolorB / 4 * Swiatlo.Count).toUint()); 
                }
            }
            Obraz.rasterize();
        }

    }
}
